/* vim: set sw=8 ts=8 sts=8 expandtab: */
#ifndef CMAID_CONTAINER_H
#define CMAID_CONTAINER_H

/* We need this for FILE */
#include <stdio.h>

/**
 * @defgroup Cmaid_Container The Container Class
 * @ingroup Classes
 * @brief The base class of all containers
 *
 * The container class builds the base of all containers, therefor it needs
 * to be general a does not provides any function that are related to the
 * underlying container layout, e.g. if the container is ordered or not, if
 * objects may appear twice etc.
 */
/**
 * @def CMAID_CONTAINER(c)
 * @ingroup Cmaid_Container
 * @brief Typecast a pointer to a Cmaid_Container pointer
 */
#define CMAID_CONTAINER(c) ((Cmaid_Container *)(c))

/**
 * @defgroup Cmaid_Container_Interface The Container Interface
 * @ingroup Cmaid_Container
 *
 * You only have to deal with the interface structure directly, if you are
 * going to write an implementation of the interface. Else you can safely
 * ignore this.
 *
 * @{
 */
/** A type definition to shorten the definition of the count callback. */
typedef int  (*Cmaid_Container_Count_Cb)(const Cmaid_Container *c);
/** A type definition to shorten the definition of the empty_is callback. */
typedef int  (*Cmaid_Container_Empty_Is_Cb)(const Cmaid_Container *c);
/** A type definition to shorten the definition of the clear callback. */
typedef void (*Cmaid_Container_Clear_Cb)(Cmaid_Container *c);
/** A type definition to shorten the definition of the iter_attach callback. */
typedef void (*Cmaid_Container_Iter_Attach_Cb)(Cmaid_Container *c, Cmaid_Iter *it);
/** A type definition to shorten the definition of the iter_detach callback. */
typedef void (*Cmaid_Container_Iter_Detach_Cb)(Cmaid_Container *c, Cmaid_Iter *it);
/** A type definition  to shorten the definition of the destroy callback. */
typedef void (*Cmaid_Container_Destroy_Cb)(Cmaid_Container *c);
/** A type definition  to shorten the definition of the dump callback. */
typedef int (*Cmaid_Container_Dump_Cb)(Cmaid_Container *c, FILE *file);
/** A type definition to shorten the definition of the node free callback. */
typedef void (*Cmaid_Container_Node_Free_Cb)(Cmaid_Container *c, void *node);

/**
 * @def CMAID_CONTAINER_INTERFACE(i)
 * @ingroup Cmaid_Container_Interface
 * @brief Typecast a pointer to a Cmaid_Container_Interface pointer
 */
#define CMAID_CONTAINER_INTERFACE(i) ((const Cmaid_Container_Interface *)(i))

/** Type definition for the @em container interface */
typedef struct Cmaid_Container_Interface Cmaid_Container_Interface;

/**
 * @brief The Container Interface structure
 * The container interface is the case interface for all containers.
 */
struct Cmaid_Container_Interface
{
        unsigned int                      magic;        /**< The magic value
                                                          of the container
                                                          interface, used for
                                                          debuging */
        Cmaid_Container_Clear_Cb          clear;        /**< The clear
                                                          callback */
        Cmaid_Container_Iter_Attach_Cb    iter_attach;  /**< The iterator
                                                          attach callback */
        Cmaid_Container_Iter_Detach_Cb    iter_detach;  /**< The iterator
                                                          dettach callback */
        Cmaid_Container_Destroy_Cb        destroy;      /**< The destroy
                                                          callback */
        Cmaid_Container_Dump_Cb           dump;         /**< The dump
                                                          callback */
        /* for internal use only */
        Cmaid_Container_Node_Free_Cb      node_free;    /**< A callback to
                                                          free a container
                                                          node. This callback
                                                          is not used by the
                                                          public API, but only
                                                          by implementation
                                                          itself */
};
/**
 * @}
 */

/**
 * @addtogroup Cmaid_Container
 * @{
 */
/**
 * @brief The Container Class structure
 * This is the base structure of every container. Do not manipulate the
 * attributes directly
 */
struct Cmaid_Container
{
        const Cmaid_Container_Interface *interface;     /**< The interface
                                                of the container */
        int count;                              /**< The count of nodes */
};

CMAID_INLINE int        cmaid_container_count(const Cmaid_Container *c);
CMAID_INLINE int        cmaid_container_empty_is(const Cmaid_Container *c);
CMAID_INLINE void       cmaid_container_clear(Cmaid_Container *c);
CMAID_INLINE void       cmaid_container_iter_attach(Cmaid_Container *c,
                                                        Cmaid_Iter *it);
CMAID_INLINE void       cmaid_container_iter_detach(Cmaid_Container *c,
                                                        Cmaid_Iter *it);
CMAID_INLINE void       cmaid_container_destroy(Cmaid_Container *c);
CMAID_INLINE int        cmaid_container_dump(Cmaid_Container *c, FILE *file);

/**
 * @}
 */
#include <cmaid_container_funcdef.h>
#endif /* CMAID_CONTAINER_H */
